package tt.dz.biz.service.task;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import tt.dz.biz.annotation.MsLog;
import tt.dz.biz.dao.common.CommonDAO;
import tt.dz.biz.dao.merch.BalanceCheckDAOImp;
import tt.dz.biz.dao.merch.ChangeDayDAOImp;
import tt.dz.biz.dao.merch.MerchAccountDetailDAOImp;
import tt.dz.biz.service.Job.JobLockService;
import tt.dz.common.BusinessException;
import tt.dz.common.DzConstants;
import tt.dz.common.DzConstants.BizType;
import tt.dz.common.DzConstants.SysState;
import tt.dz.common.DzConstants.bizSysCode;
import tt.dz.common.DzConstants.curBalType;
import tt.dz.common.DzConstants.jobStatus;
import tt.dz.common.DzConstants.sysJob;
import tt.dz.common.LogUtil;
import tt.dz.vo.BalanceCheckVO;
import tt.dz.vo.BorrowLoanCheckVO;
import tt.dz.vo.ChangeDayVO;
import tt.dz.vo.JobLockVO;

@Service("calcBalanceTask")
public class CalcBalanceTaskService
  extends DailyTaskService
{
  @Resource(name="changeDayDAO")
  protected ChangeDayDAOImp changeDayDAOImp;
  @Resource(name="commonDAO")
  protected CommonDAO commonDAO;
  @Resource(name="jobLockService")
  protected JobLockService jobLockService;
  @Resource(name="merchAccountDetailDAO")
  MerchAccountDetailDAOImp merchAccountDetailDAO;
  @Resource(name="balanceCheckDAO")
  BalanceCheckDAOImp balanceCheckDAO;
  
  @MsLog(bizCode="calcBalanceTask", bizName="试算平衡任务", bizType=DzConstants.BizType.JOB, bizDesc="此任务只包含试算平衡")
  public void execute()
    throws Exception
  {
    try
    {
      LogUtil.info("试算平衡JOB执行开始");
      beforeExecuteTask();
      
      ChangeDayVO changeDay = this.changeDayDAOImp.queryChangeDay();
      Date accountingDate = changeDay.getYtdAccountingDate();
      Assert.notNull(accountingDate, "查询会计账务日期为空，请检查！");
      LogUtil.debug("会计账务日期：" + accountingDate);
      
      List<?> l = this.balanceCheckDAO.queryBalanceCheckByAccoutingDate(accountingDate);
      if (CollectionUtils.isNotEmpty(l)) {
        this.balanceCheckDAO.deleteBalanceCheckByAccoutingDate(accountingDate);
      }
      Map<String, BigDecimal> DetailChangeMap = new HashMap();
      List<BalanceCheckVO> balanceCheckList = new ArrayList();
      
      List<Map<String, Object>> DetailChangeList = this.merchAccountDetailDAO.queryChangeAmountForDetailByAccountingDate(accountingDate);
      LogUtil.debug("运营商内部帐户明细表数据记录数：" + (DetailChangeList != null ? DetailChangeList.size() : 0));
      List<Map<String, Object>> subjectAccChangeList = this.merchAccountDetailDAO.queryChangeAmountForSubjectAcc();
      LogUtil.debug("运营商内部帐户信息表数据记录数：" + (subjectAccChangeList != null ? subjectAccChangeList.size() : 0));
      for (Map<String, Object> DetailChangerow : DetailChangeList)
      {
        String merchantCode = (String)DetailChangerow.get("merchantCode");
        String subSubjectCode = (String)DetailChangerow.get("subSubjectCode");
        BigDecimal changeAmount = (BigDecimal)DetailChangerow.get("changeAmount");
        String key = merchantCode + "`" + subSubjectCode;
        DetailChangeMap.put(key, changeAmount);
      }
      LogUtil.debug("运营商内部帐户明细表数据Map加工完成，记录数：" + DetailChangeMap.size());
      for (Map<String, Object> subjectAccChangerow : subjectAccChangeList)
      {
        BalanceCheckVO balanceCheckVo = new BalanceCheckVO();
        String merchantCode = (String)subjectAccChangerow.get("merchantCode");
        String subSubjectCode = (String)subjectAccChangerow.get("subSubjectCode");
        BigDecimal subjectAmount = (BigDecimal)subjectAccChangerow.get("changeAmount");
        String key = merchantCode + "`" + subSubjectCode;
        BigDecimal dailyAmount = (BigDecimal)DetailChangeMap.get(key);
        dailyAmount = dailyAmount != null ? dailyAmount : BigDecimal.ZERO;
        subjectAmount = subjectAmount != null ? subjectAmount : BigDecimal.ZERO;
        balanceCheckVo.setMerchantCode(merchantCode);
        balanceCheckVo.setSubSubjectCode(subSubjectCode);
        balanceCheckVo.setDailyAmount(dailyAmount);
        balanceCheckVo.setSubjectAmount(subjectAmount);
        balanceCheckVo.setAccountingDate(accountingDate);
        if (dailyAmount.compareTo(subjectAmount) == 0) {
          balanceCheckVo.setCurBal(DzConstants.curBalType.BALANCE.value());
        } else {
          balanceCheckVo.setCurBal(DzConstants.curBalType.UNBALANCE.value());
        }
        balanceCheckList.add(balanceCheckVo);
      }
      LogUtil.debug("试算平衡数据装配完成，记录数：" + balanceCheckList.size());
      
      this.balanceCheckDAO.insertBatchBalanceCheck(balanceCheckList);
      
      dealBorrowLoanCheck(accountingDate);
      
      afterExecuteTask();
    }
    catch (Exception e)
    {
      LogUtil.error("写入试算平衡发生异常!" + e);
      throw e;
    }
    LogUtil.info("试算平衡JOB执行完成");
  }
  
  protected void beforeExecuteTask()
    throws Exception
  {
    this.jobvo = this.jobLockService.updateJobStatusForLock(DzConstants.sysJob.CALC_BALANCE_TASK.value());
    if (null == this.jobvo) {
      throw new BusinessException("锁试算平衡任务（" + DzConstants.sysJob.CALC_BALANCE_TASK.value() + "）失败，不能执行！！！");
    }
    String stateCode = this.commonDAO.getCurrentSysState(DzConstants.bizSysCode.MAIN_SERVER.value());
    if (!this.jobvo.getStateCode().equals(stateCode)) {
      throw new BusinessException("系统状态为" + stateCode + "与试算平衡任务需要的状态" + DzConstants.SysState.DAILY_ACCOUNTED.value() + "不一致，不能执行试算平衡任务。");
    }
  }
  
  protected void afterExecuteTask()
    throws Exception
  {
    this.jobvo.setStatus(DzConstants.jobStatus.WAITING.value());
    this.jobLockService.updateJobStatusForRestart(this.jobvo);
    try
    {
      this.jobLockService.updateLastRunTimeByCode(this.jobvo.getJobCode());
      int i = this.commonDAO.updateSysCurrentState(DzConstants.SysState.NORMAL_RUNNING.value());
      if (i < 1) {
        throw new Exception("试算平衡任务（calcBalanceTask）后更新系统当前状态失败！");
      }
    }
    catch (Exception e)
    {
      LogUtil.error("试算平衡任务完成处理异常，jobcode为：" + this.jobvo.getJobCode(), e);
      throw e;
    }
  }
  
  private void dealBorrowLoanCheck(Date accountingDate)
    throws Exception
  {
    List<?> l = this.balanceCheckDAO.queryBorrowLoanCheckByAccoutingDate(accountingDate);
    if (CollectionUtils.isNotEmpty(l)) {
      this.balanceCheckDAO.deleteBorrowLoanCheckByAccoutingDate(accountingDate);
    }
    BorrowLoanCheckVO vo = this.balanceCheckDAO.queryBorrowAndLoanAccoutingByDate(accountingDate);
    vo.setAccountingDate(accountingDate);
    if (vo.getBorrowAmount().compareTo(vo.getLoanAmount()) == 0) {
      vo.setIsBal(DzConstants.curBalType.BALANCE.value());
    } else {
      vo.setIsBal(DzConstants.curBalType.UNBALANCE.value());
    }
    this.balanceCheckDAO.insertBorrowLoanCheck(vo);
  }
}
